package pl.edu.ii.uj.battleships.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.Message;
import pl.edu.uj.ii.battleships.interfaces.Handler;
import pl.edu.uj.ii.battleships.utils.ConfigPropsManager;
import pl.edu.uj.ii.battleships.utils.GameDataManager;
import pl.edu.uj.ii.battleships.utils.Logger;
import pl.edu.uj.ii.battleships.utils.MessageFactory;


public class ServerHandler extends Thread {
	ConfigPropsManager propsManager;
	private Socket socket = null;
	private ObjectOutputStream out = null;
	private ObjectInputStream in = null;
	Logger logger = Logger.getInstance(this.getClass().getSimpleName());
	Handler handler;
	PackageServer packageS;
	
	boolean running = true;
	
	public ServerHandler(ConfigPropsManager propsMan, Handler h){
		propsManager = propsMan;
		handler = h;
		
	}
	
	public void run(){
		Logger.debug("ServerHandler started.");
		
		if(establishConnection())
			sendMessageToHandler(MessageFactory.Prefix.CONNECTION + MessageFactory.getDelimiter() + MessageFactory.Status.OK);
		else 
			sendMessageToHandler(MessageFactory.Prefix.CONNECTION + MessageFactory.getDelimiter() + MessageFactory.Status.FAILED);
		
		
		while(running){
			 try {
	            packageS = (PackageServer)in.readObject();
             } catch(Exception e) {
            	sendMessageToHandler(MessageFactory.Prefix.CONNECTION + MessageFactory.getDelimiter() + MessageFactory.Status.LOST);
                break;
             }
		 
			 checkPackage(packageS);
		}
		
		Logger.debug("ServerHandler ending.");
	}
	
	
	private void checkPackage(PackageServer pack) {
		Logger.debug("Received package.");
		Logger.debug("Status: " + pack.getStatus() + "  Message: " + pack.getMessage() + "  FromOpponent: " + pack.getOpponent());
		if(!GameDataManager.getMyNick().equals(pack.getOpponent())){
			Logger.error("Message not for this client. This client: " + GameDataManager.getMyNick() +
					      "  Receiver: " + pack.getOpponent());
		} else {
		
			switch (pack.getStatus()) {
			case 1:
				Logger.debug("Opponent registered.");
				Logger.debug("Login: " + pack.getOpponent());
				GameDataManager.setOpponentNick(pack.getOpponent());
				sendMessageToHandler(MessageFactory.Prefix.GAME + MessageFactory.getDelimiter() + "start");
				break;
				
			case 2: 
				break;
			default:
				Logger.debug("Received unknown message");
				break;
			}
		}
	}

	public boolean establishConnection() {
		boolean state = true;
		
		Logger.debug("Trying to connect to server");
		String server = propsManager.getValue("server.address", "127.0.0.1");
		String port = propsManager.getValue("server.port", "23232");
		Logger.debug("Server: " + server + ":" + port);
		
        InetAddress address = null;
		try {
			address = InetAddress.getByName(server);
	        socket = new Socket(address,Integer.parseInt(port));
	        setOutputStream(new ObjectOutputStream (socket.getOutputStream()));
	        in = new ObjectInputStream (socket.getInputStream());
		} catch (UnknownHostException e) {
			Logger.error("Unknown host " + server, e);
			state = false;
		} catch (NumberFormatException e) {
			Logger.error("Unexpected exception", e);
			state = false;
		} catch (IOException e) {
			Logger.error("Failed to connect to server", e);
			state = false;
		}
		
		return state;
	}
	
	public void sendMessageToHandler(String mes){
    	Message msg = handler.getHandler().obtainMessage();
    	msg.obj = new String(mes);
    	handler.getHandler().sendMessage(msg);
	}
	
	public void sendPackage(PackageClient packageC){
		try {
	           out.writeObject(packageC);
	           out.flush();
		} catch(Exception e) {
			 System.err.println("Sendpackage error: " + e);                  
			 //clients.remove(login);
			 //readyPlayers.remove(login);
			 //lobbyPlayers.remove(login);
			//System.out.println("Clients: " + clients.size());  
			 
			running = false;
		}
	}

	public ObjectOutputStream getOutputStream() {
		return out;
	}

	public void setOutputStream(ObjectOutputStream out) {
		this.out = out;
	}
	
	public void setHandler(Handler h){
		this.handler = h;
	}
}
